﻿using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using MathNet.Numerics;
using MathNet.Numerics.LinearAlgebra;
using MathNet.Numerics.Statistics;
using OfficeOpenXml;
using MathNet.Numerics.Differentiation;
using System.Windows.Forms.DataVisualization.Charting;
using UnscentedKalmanFilter;

namespace FliterLearn
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }


        private List<Tuple<double, double>> Truch()
        {
            string path = @"C:\Users\Embeded\Desktop\滤波实验.xlsx";
            var file = new ExcelPackage(new FileStream(path, FileMode.Open));
            var sheet = file.Workbook.Worksheets["Sheet1"];
            int i = 2; // 从第2行开始读
            var data = new List<Tuple<double, double>>();
            while (true)
            {
                var time = sheet.Cells[i, 1].Value;
                var CN = sheet.Cells[i, 6].Value;
                if (time != null)
                {
                    data.Add(new Tuple<double, double>((double)i, (double)CN));
                }
                else
                {
                    break;
                }
                i++;
            }
            return data;
        }
        private List<Tuple<double, double>> Static()
        {
            var data = new List<Tuple<double, double>>();
            var x = 5;
            var r = new Random();
            for (int i = 0; i < 500; i++)
            {
                var mock = x + r.NextDouble() * Math.Sqrt(5) * 5;
                data.Add(new Tuple<double, double>(i, mock));
            }

            for (int i = 500; i < 1000; i++)
            {
                var mock = x+10 + r.NextDouble() * Math.Sqrt(5) * 5;
                data.Add(new Tuple<double, double>(i, mock));
            }

            for (int i = 1000; i < 1500; i++)
            {
                var mock = x - 20 + r.NextDouble() * Math.Sqrt(5) * 5;
                data.Add(new Tuple<double, double>(i, mock));
            }

            for (int i = 1500; i < 2000; i++)
            {
                var mock = x - 18 + r.NextDouble() * Math.Sqrt(5) * 5;
                data.Add(new Tuple<double, double>(i, mock));
            }

            return data;
        }
        private List<Tuple<double, double>> Uniform()
        {
            var data = new List<Tuple<double, double>>();
            var x = 5;
            var r = new Random();
            for (int i = 0; i < 500; i++)
            {
                var mock = 2*i + x + r.NextDouble() * Math.Sqrt(5) * 200;
                data.Add(new Tuple<double, double>(i, mock));
            }
            return data;
        }

        private List<Tuple<double, double>> Acc()
        {
            var data = new List<Tuple<double, double>>();
            var x = 5;
            var r = new Random();
            for (int i = 0; i < 100; i++)
            {
                var mock =  i * i + 1.2 * i + x + r.NextDouble() * Math.Sqrt(5) * 500;
                data.Add(new Tuple<double, double>(i, mock));
            }

            for (int i = 100; i < 200; i++)
            {
                var mock = -0.5*i * i +  i + x + r.NextDouble() * Math.Sqrt(5) * 500 + data[99].Item2;
                data.Add(new Tuple<double, double>(i, mock));
            }

            return data;
        }

        private bool IsContinueInc(double[] data)
        {
            int count = 0;
            for (int i = 1; i < data.Count(); i++)
            {
                if (data[i] - data[i-1] > 0.2)
                {
                    count++;
                }
            }
            return count >= 8;
        }

        private bool IsContinueSub(double[] data)
        {
            int count = 0;
            for (int i = 1; i < data.Count(); i++)
            {
                if (data[i] - data[i - 1] < -0.2)
                {
                    count++;
                }
            }
            return count >= 8;
        }

        private double GetError(double[] data)
        {
            if (IsContinueInc(data))
            {
                return (data.Max() - data.Min());
            }
            else
            {
                return (data.Min() - data.Max());
            }

        }
        private void btRun_Click(object sender, EventArgs e)
        {
            chart1.Series[0].Points.Clear();
            chart1.Series[1].Points.Clear();

            var data = Static();

            if (rbTruch.Checked)
            {
                data = Truch();
            }
            else if (rbConstant.Checked)
            {
                data = Uniform();
            }
            else if (rbAcc.Checked)
            {
                data = Acc();
            }

            foreach (var d in data)
            {
                chart1.Series[0].Points.AddXY(d.Item1, d.Item2);
            }

            FilterHelp filter = new StaticModel();
            if (rbUniformMod.Checked)
            {
                filter = new UniformModel();
            }
            else if (rbAccMod.Checked)
            {
                filter = new AccModel();
            }
            else if (rbUnstrace.Checked)
            {
                filter = new UKF();
            }

            foreach (var d in data)
            {
                var hat = filter.Update(d.Item2);
                chart1.Series[1].Points.AddXY(d.Item1, hat);
            }

        }

        private void btSave_Click(object sender, EventArgs e)
        {

        }

        private void chart1_GetToolTipText(object sender, System.Windows.Forms.DataVisualization.Charting.ToolTipEventArgs e)
        {
            HitTestResult myTestResult = chart1.HitTest(e.X, e.Y, ChartElementType.DataPoint);//获取命中测试的结果

            if (myTestResult.ChartElementType == ChartElementType.DataPoint)
            {
                int i = myTestResult.PointIndex;
                DataPoint dp = myTestResult.Series.Points[i];
                string YValue = dp.YValues[0].ToString("F2");//获取数据点的Y值
                string XValue = dp.XValue.ToString();
                e.Text = $"X:{XValue}     Y:{YValue}";
            }
        }
    }
}
